// ==================================================================================
// Shared Genomics Project MPI Codebase
// Version 1.0 30/04/2010
//
// (c) 2010 University of Manchester all rights reserved
//
// This file is distributed under the GNU General Public License, Version 2.  
// Please see the file COPYING.txt for more details
// ==================================================================================

/*!
\file
\brief Implementation of Person Missingness Functions 
*/

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include "chromosomes.h"
#include "copyfile.h"
#include "locus.h"
#include "missingnessfile.h"
#include "pedfile.h"
#include "suffixes.h"
#include "utils.h"

int missingnessfile_create(struct mapfile *m, struct pedfile *p, struct selected_options *ops, struct chromosomes *chromos) {
	BOOL jobDone = FALSE;
	char filepath[FILE_PATH_LENGTH];
	int i, j;
	FILE *out = NULL;

	if (m == NULL || ops == NULL || p == NULL) return 0;
	else if (m->nSNP == 0 || p->nSample == 0) return 0;
	else if (strlen(ops->szRunId) == 0 || strlen(ops->ldir) == 0) return 0;

	sprintf(filepath, "%s%s%s", ops->ldir, ops->szRunId,  SUFFIX_PERSON_MISSINGNESS);
	out = fopen(filepath, "w");
	if (out) {
		// Consider each individual
		int nSamples = m->SNP[0]->nOne;
		fprintf(out, "%i\n", nSamples);
		for (i = 0; i < nSamples; i++) {
			BOOL female = !p->sample[i]->sex ? TRUE: FALSE;
			int _m = 0;       // Missing SNPs
			int nsnps = 0;   // All non-obligatory missing SNPs
			double missingness_ratio = 0.0;

			for (j = 0; j < m->nSNP; j++) {
				// Skip female Y chromosomes
				if (female && chromos->chr_Y[m->locus[j]->chr]) continue;
				nsnps++;
				if (m->SNP[j]->one[i] && ! m->SNP[j]->two[i]) _m++; // Missing Allele (T & F coding in PLINK-speak.)
			}

			if (_m > 0 && nsnps > 0) missingness_ratio = (double) _m / (double) nsnps;
			fprintf(out, "%2.16f\n", missingness_ratio);
		}
		fclose(out);
		jobDone = TRUE;
	}

	if (jobDone) return 1;
	else return 0;
}

double* missingnessfile_load(struct selected_options *ops, int *nSamples) {
	FILE *in = NULL;
	char line[80];
	double *values = NULL;
	int _nSamples = 0, lineCount = 0;

	if (ops == NULL || nSamples == NULL) return values;
	else if (strlen(ops->szMissingnessFileName) == 0) return values;

	*nSamples = 0;
	
	in = fopen(ops->szMissingnessFileName, "r");
	if (in != NULL) {
		fgets(line, 80, in);
		_nSamples = atoi(line);
		if (_nSamples > 0) {
			values = create_vector(_nSamples, 0);
			if (values != NULL) {
				while(fgets(line, 80, in)) {
					values[lineCount++] = atof(line);
					if (lineCount == _nSamples) break;
				}
				if (lineCount != _nSamples) {
					// Truncated data, so drop the values array to flag an error.
					free(values);
					values = NULL;
				} else {
					// If here, okay so set the size pointer on the array.
					*nSamples = _nSamples;
				}
			}
		}
		fclose(in);
	}

	return values;
}

// Locally temporarily appending rank to the run ID to increase the uniqueness of the output file name.
int missingnessfile_create_and_copy(struct mapfile *m, struct pedfile *p, struct selected_options *ops, struct chromosomes *chromos, int rank) {
	BOOL jobDone = FALSE;
	char tmp_szRunId[TOKEN_LENGTH];

	if (m == NULL || ops == NULL || chromos == NULL || p == NULL) return 0;

	strcpy(tmp_szRunId, ops->szRunId);
	sprintf(ops->szRunId, "%s_%i", tmp_szRunId, rank);
	if (missingnessfile_create(m, p, ops, chromos)) {
		char localFilepath[FILE_PATH_LENGTH], remoteFilepath[FILE_PATH_LENGTH];
		sprintf(localFilepath, "%s%s%s", ops->ldir, ops->szRunId, SUFFIX_PERSON_MISSINGNESS);
		sprintf(remoteFilepath, "%s%s%s", ops->rdir, tmp_szRunId, SUFFIX_PERSON_MISSINGNESS);
		if (copyAndDeleteFile(localFilepath, remoteFilepath)) jobDone = TRUE;
	}

	strcpy(ops->szRunId, tmp_szRunId); // Restore the original Run ID

	if (jobDone) return 1;
	else return 0;
}